from PIL import Image, ImageTk
import os
import VocXml as VocXml
from VocXml import GEN_Annotations
from LogUtils import logger
import time
import ImageUtils


class ImageTag:

    def __init__(self, imagePath, imageSize):
        self.__imagePath = imagePath  # 图片路径
        self.__xmlPath = imagePath.split(".")[0] + ".xml"  # 该图片对应的xml文件路径
        self.isTag = False  # 是否具有xml文件
        self.imageLength = 0  # 原始图片大小，为了后面的标注计算用
        self.image = self.rectangularImage(self.__imagePath, self.__imagePath, imageSize)  # 只是用于填充画布的Image
        self.LabelList = []  # 标签集合{}
        self.rects = []  # 矩形框集合
        self.labelIndex = len(self.LabelList) - 1  # 该图片未标注时，该值为-1

        self.isSave = False
        self.initXmlFile()

    def IsSave(self):
        return self.isSave



    def getXmlPath(self):
        return self.__xmlPath


    def getCurrentRect(self):
        return self.rects[len(self.rects) - 1]

    def getImage(self):
        return self.image

    def getImageLength(self):
        return self.imageLength

    def pushLabelAndRect(self, label, rect):
        """
        标签和矩形框一起入栈,用于绘制矩形时同步添加
        :param label: ["person",234,23,4,23] 注意格式
        :param rect:
        :return:
        """
        # 入栈 标签保证签名的坐标比后面的坐标小
        xmin = min(label[1], label[3])
        ymin = min(label[2], label[4])
        xmax = max(label[1], label[3])
        ymax = max(label[2], label[4])
        label = {"name": label[0], "xmin": xmin, "ymin": ymin, "xmax": xmax, "ymax": ymax}
        self.LabelList.append(label)
        self.rects.append(rect)
        self.labelIndex = len(self.LabelList) - 1
        logger.debug("入栈后检查栈{0},{1}".format(self.LabelList, self.rects))
        self.isSave = False

    def popLabelAndRect(self):
        """
        将标签和矩形框出栈
        :return: 返回出栈的矩形框，用于删除标注
        """
        logger.debug("ImageTag出栈前检查{0},{1}".format(len(self.LabelList), len(self.rects)))
        if len(self.LabelList) > 0 and len(self.rects) > 0:
            self.LabelList.pop()
            rect = self.rects.pop()
            self.labelIndex = len(self.LabelList) - 1
            self.isSave = False
            logger.debug("出栈完成检查（LabelList，rects）{0},{1}".format(len(self.LabelList), len(self.rects)))
            return rect
        else:
            logger.debug("标签和矩形框的栈为空")
            return None

    def getLabelList(self):
        """
        获取所有LabelList ，主要用于后期图片切换时，生成矩形框
        :return:
        """
        return self.LabelList

    def initXmlFile(self):
        """
        初始化xml,读取并不保存
        :return:
        """
        logger.debug("检查本次读取到的xml文件路径{0}".format(self.__xmlPath))
        if os.path.exists(self.__xmlPath):
            self.isTag = True
            labels = VocXml.readTagFromFile(self.__xmlPath)
            logger.debug("读取到本张照片的xml文件中的labels有{0}".format(labels))
            for label in labels:
                self.LabelList.append({"name": label["name"],
                                       "xmin": label["xmin"] * 800 // self.imageLength,
                                       "ymin": label["ymin"] * 800 // self.imageLength,
                                       "xmax": label["xmax"] * 800 // self.imageLength,
                                       "ymax": label["ymax"] * 800 // self.imageLength})
        self.isSave = True

    def pushRect(self, rect):
        """
        单独矩形框入栈，因为新打开一张图片时，标签是由initXmlFile从xml文件中读取到的，后由界面手动画出的矩形，这些矩形并没有入栈，
        该方法就是提供给自动生成的矩形框入栈使用的，其他情况不得调用
        :param rect: 入栈的矩形框
        :return:
        """
        logger.debug("新的矩形入栈{0}".format(rect))
        self.rects.append(rect)

    def checkLabelAndRect(self):
        logger.debug("检查栈内的矩形框与标签是否对等 {0} {1}".format(self.rects, self.LabelList))

    def saveTagXml(self):
        """
        保存xml标注
        :return:
        """

        annotations = GEN_Annotations(self.__imagePath)
        annotations.set_size(self.imageLength, self.imageLength, 3)
        for item in self.LabelList:
            annotations.add_pic_attr(item["name"], item["xmin"] * self.imageLength // 800,
                                     item["ymin"] * self.imageLength // 800, item["xmax"] * self.imageLength // 800,
                                     item["ymax"] * self.imageLength // 800)
        annotations.savefile(self.__xmlPath)
        self.isSave = True
        logger.debug("保存成功")

    def rectangularImage(self, originImagePath, saveImagePath, imageSize):
        """
        先判断该图片是否存在标注文件，有就直接返回图片，没有就去黑边然后填充为正方形，将图片填充为正方形,返回重置大小的图片
        :param originImagePath: 原始图片路径
        :param saveImagePath: 保存图片路径
        :param imageSize: 希望返回的图片的大小
        :return: 返回指定大小的图片
        """
        xmlPath = originImagePath.split(".")[0] + ".xml"
        if not os.path.exists(xmlPath):
            ImageUtils.handleImage(originImagePath, saveImagePath)
        originImage = Image.open(originImagePath)
        logger.debug("本次读取的图片的的长度为 {0}".format(originImage.size[0]))
        length = max(originImage.size[0], originImage.size[1])
        self.imageLength = length  # 设置为原始图片大小
        if originImage.size[0] == originImage.size[1]:
            # 图片本来就是正方形的
            changeResizeImage = originImage.resize((imageSize, imageSize))  ##重新设置大小，使之能刚刚好填充cavans
            changeResizeImage = ImageTk.PhotoImage(changeResizeImage)
            return changeResizeImage
        else:
            # 如果图片不是正方形的
            changeImage = Image.new('RGB', (length, length), (0, 0, 0))
            changeImage.paste(originImage,
                              (int((length - originImage.size[0]) / 2), int((length - originImage.size[1]) / 2)))
            changeImage.save(saveImagePath)
            changeResizeImage = changeImage.resize((imageSize, imageSize))  ##重新设置大小，使之能刚刚好填充cavans
            changeResizeImage = ImageTk.PhotoImage(changeResizeImage)
            return changeResizeImage
